using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Transactions;
using THSLib;
using THSERP.BaseProvider;
using THSERP.BusinessEntities;
namespace THSERP.Modules.LayBy
{
    public class LayByEntities : ERPModuleEntities
    {
        #region Declare Constant
        #endregion

        #region Declare all entities variables
        private ARSaleOrdersInfo _aRSaleOrdersObject;
        private ARSaleOrderItemsInfo _aRSaleOrderItemsObject;

        public THSItemsEntityList<SaleOrderItemsEntity> lstARSaleOrderItems;
        public THSList<ARDocumentPaymentDetailsInfo> lstARDocumentPaymentDetails;
        private bool IsActionComplete = false;
        #endregion

        #region Public Properties
        public ARSaleOrdersInfo ARSaleOrdersObject
        {
            get
            {
                return _aRSaleOrdersObject;
            }
            set
            {
                _aRSaleOrdersObject = value;
            }
        }
        public ARSaleOrderItemsInfo ARSaleOrderItemsObject
        {
            get
            {
                return _aRSaleOrderItemsObject;
            }
            set
            {
                _aRSaleOrderItemsObject = value;
            }
        }

        public THSItemsEntityList<SaleOrderItemsEntity> ARSaleOrderItemsList
        {
            get
            {
                return lstARSaleOrderItems;
            }
            set
            {
                lstARSaleOrderItems = value;
            }
        }

        public THSList<ARDocumentPaymentDetailsInfo> ARDocumentPaymentDetailsList
        {
            get
            {
                return lstARDocumentPaymentDetails;
            }
            set
            {
                lstARDocumentPaymentDetails = value;
            }
        }
        #endregion

        #region Constructor
        public LayByEntities()
            : base()
        {
            _aRSaleOrdersObject = new ARSaleOrdersInfo();   

            _aRSaleOrderItemsObject = new ARSaleOrderItemsInfo();

            lstARSaleOrderItems = new THSItemsEntityList<SaleOrderItemsEntity>();
        }

        #endregion

        #region Init Main Object,Module Objects functions
        public override void InitMainObject()
        {
            MainObject = ARSaleOrdersObject;
        }

        public override void InitModuleObjects()
        {
            ModuleObjects.Add("ARSaleOrderItems", ARSaleOrderItemsObject);
        }

        public override void InitModuleObjectList()
        {
            lstARSaleOrderItems = new THSItemsEntityList<SaleOrderItemsEntity>();
            lstARSaleOrderItems.InitTHSList(this,
                 THSUtil.GetTableNameFromBusinessObjectType(typeof(ARSaleOrdersInfo)),
                 THSUtil.GetTableNameFromBusinessObjectType(typeof(ARSaleOrderItemsInfo)));
        }

        public override void InitGridControlInTHSList()
        {
            lstARSaleOrderItems.InitTHSListGridControl("fld_dgcARLayByItems");
        }

        public override void SetDefaultModuleObjectsList()
        {
            try
            {
                lstARSaleOrderItems.SetDefaultListAndRefreshGridControl();
            }
            catch (Exception)
            {
                return;
            }
        }

        #endregion

        #region Invalidate Module Objects Functions
        public override void InvalidateModuleObjects(int iObjectID)
        {
            ARSaleOrderItemsList.Invalidate(iObjectID);
            ICProductAttributesController objProductAttributesController = new ICProductAttributesController();
            foreach (SaleOrderItemsEntity entItem in ARSaleOrderItemsList)
            {
                entItem.ARSaleOrderItemProductAttribute = objProductAttributesController.GetAttributeValueByProductAttributeID(entItem.FK_ICProductAttributeID);
            }
            if (ARSaleOrderItemsList.Count > 0)
                ARSaleOrderItemsList.GridViewFocusRow(0);
        }
        #endregion

        #region Save Module Objects Functions
        public override int SaveMainObject()
        {
            ARSaleOrderItemsList.EndCurrentEdit();
            UpdateTotalAmount();
            return base.SaveMainObject();
        }
        public override void SaveModuleObjects()
        {
            //Decrease sale order quantity of original list
            foreach (SaleOrderItemsEntity entItem in ARSaleOrderItemsList.OriginalList)
                UpdateInventory(entItem, BusinessObject.DeletedAAStatus);
            ARSaleOrderItemsList.SaveItemObjects();
            //Update new sale order quantity
            ARSaleOrderItemsList.UpdateInventory(BusinessObject.DefaultAAStatus);
        }
        #endregion

        public override void DoActionAfterRemovingItemObject(string strItemTableName)
        {
            UpdateTotalAmount();
        }

        public override void SetValuesAfterValidateProduct(int productAttributeID)
        {
            ICProductAttributesController objProductAttributesController = new ICProductAttributesController();
            ICProductAttributesInfo objProductAttributesInfo = (ICProductAttributesInfo)objProductAttributesController.GetObjectByID(productAttributeID);
            if (objProductAttributesInfo != null)
            {
                ARSaleOrderItemsInfo objSaleOrderItemsInfo = (ARSaleOrderItemsInfo)ModuleObjects[SaleOrder.SaleOrderEntities.strARSaleOrderItemsObjectName];
                objSaleOrderItemsInfo.FK_ICProductID = objProductAttributesInfo.FK_ICProductID;
                ARSaleOrderItemsList.SetDefaultValuesFromProduct(objProductAttributesInfo.FK_ICProductID);
                objSaleOrderItemsInfo.FK_ICStockID = ((ARSaleOrdersInfo)MainObject).FK_ICStockID;
                objSaleOrderItemsInfo.FK_ICDepartmentID = objProductAttributesInfo.FK_ICDepartmentID;
                objSaleOrderItemsInfo.FK_ICProductGroupID = objProductAttributesInfo.FK_ICProductGroupID;
                objSaleOrderItemsInfo.FK_ICProductAttributeID = objProductAttributesInfo.ICProductAttributeID;
                objSaleOrderItemsInfo.ARSaleOrderItemProductAttribute = objProductAttributesController.GetAttributeValueByProductAttributeID(objProductAttributesInfo.ICProductAttributeID);
                objSaleOrderItemsInfo.ARSaleOrderItemProductSerialNo = objProductAttributesInfo.ICProductAttributeSerialNo;
                UpdateModuleObjectBindingSource(SaleOrder.SaleOrderEntities.strARSaleOrderItemsObjectName);
            }
        }

        public void SetDefaultValuesFromCustomer(ARCustomersInfo objCustomersInfo, bool applyCustomerPriceLevel)
        {
            if (applyCustomerPriceLevel)
            {
                //Update price level of sale receipt
                ((ARSaleOrdersInfo)MainObject).FK_ARPriceLevelID = objCustomersInfo.FK_ARPriceLevelID;
                UpdateMainObjectBindingSource();

                //Update all item price basing on price level
                foreach (SaleOrderItemsEntity entItem in ARSaleOrderItemsList)
                    SetProductPrice(entItem, SaleOrder.SaleOrderEntities.strARSaleOrderItemsObjectName);
                ARSaleOrderItemsList.GridControl.RefreshDataSource();
                UpdateTotalAmount();
            }
        }

        public void UpdateTotalAmount()
        {
            if (!Module.Toolbar.IsNullOrNoneAction())
            {
                ARSaleOrdersInfo objSaleOrdersInfo = (ARSaleOrdersInfo)MainObject;
                objSaleOrdersInfo.ARSaleOrderNetAmount = 0;
                objSaleOrdersInfo.ARSaleOrderTaxAmount = 0;
                objSaleOrdersInfo.ARSaleOrderSubTotalAmount = 0;
                foreach (SaleOrderItemsEntity entItem in ARSaleOrderItemsList)
                {
                    objSaleOrdersInfo.ARSaleOrderNetAmount += entItem.ARSaleOrderItemNetAmount;
                    objSaleOrdersInfo.ARSaleOrderTaxAmount += entItem.ARSaleOrderItemTaxAmount;
                    objSaleOrdersInfo.ARSaleOrderSubTotalAmount += entItem.ARSaleOrderItemTotalAmount;
                }
                objSaleOrdersInfo.ARSaleOrderDiscountFix = objSaleOrdersInfo.ARSaleOrderSubTotalAmount * objSaleOrdersInfo.ARSaleOrderDiscountPerCent / 100;
                objSaleOrdersInfo.ARSaleOrderTotalAmount = objSaleOrdersInfo.ARSaleOrderSubTotalAmount - objSaleOrdersInfo.ARSaleOrderDiscountFix;
                objSaleOrdersInfo.ARSaleOrderBalanceDue = objSaleOrdersInfo.ARSaleOrderTotalAmount - objSaleOrdersInfo.ARSaleOrderDepositBalance;
                UpdateMainObjectBindingSource();
            }
        }

        public int TakePayment(double totalAmount)
        {
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
            {
                try
                {
                    //Generate invoice
                    ARInvoicesController objInvoicesController = new ARInvoicesController();
                    ARInvoicesInfo objInvoicesInfo = GenerateInvoiceFromSaleOrder((ARSaleOrdersInfo)MainObject);
                    objInvoicesInfo.ARInvoiceNo = THSApp.GetMainObjectNo("Invoice");
                    objInvoicesInfo.ARInvoiceTotalAmount = totalAmount;

                    int iInvoiceID = objInvoicesController.CreateObject(objInvoicesInfo);
                    THSApp.UpdateObjectNumbering("Invoice");

                    //Generate open document
                    AROpenDocumentsController objOpenDocumentsController = new AROpenDocumentsController();
                    AROpenDocumentsInfo objOpenDocumentsInfo = CustomerPayment.CustomerPaymentModule.GenerateOpenDocumentFromInvoice(objInvoicesInfo);
                    objOpenDocumentsController.CreateObject(objOpenDocumentsInfo);
                    CustomerPayment.CustomerPaymentModule.TakePayment(objOpenDocumentsInfo, totalAmount, ARDocumentPaymentDetailsList);
                    scope.Complete();
                    return iInvoiceID;
                }
                catch (Exception ex)
                {
                    scope.Dispose();
                    return 0;
                }
            }
        }

        public override bool CompleteTransaction()
        {
            ARSaleOrdersInfo objSaleOrdersInfo = (ARSaleOrdersInfo)MainObject;

            ARInvoicesController objInvoicesController = new ARInvoicesController();
            ARInvoicesInfo objInvoicesInfo = objInvoicesController.GetInvoiceByReference(objSaleOrdersInfo.ARSaleOrderNo);
            if (objInvoicesInfo != null)
            {
                //Generate all items of invoice
                CreateInvoiceItemsFromSaleOrderItems(objInvoicesInfo.ARInvoiceID);
            }

            //Update SaleOrder status
            ARSaleOrdersController objSaleOrdersController = new ARSaleOrdersController();
            objSaleOrdersInfo.AAUpdatedDate = DateTime.Now;
            objSaleOrdersInfo.AAUpdatedUser = THSApp.CurrentUser;
            objSaleOrdersInfo.ARSaleOrderStatus = LayByModule.cstLayByStatusComplete;
            objSaleOrdersController.UpdateObject(MainObject);

            //Update Inventory
            //Update sale order quantity
            ARSaleOrderItemsList.UpdateInventory(BusinessObject.DeletedAAStatus);
            //Update on-hand quantity
            IsActionComplete = true;
            ARSaleOrderItemsList.UpdateInventory(BusinessObject.DefaultAAStatus);
            IsActionComplete = false;

            return true;
        }

        public override bool IsInvalidInventory()
        {
            return ARSaleOrderItemsList.IsInvalidInventory(TransactionUtil.cstInventoryShipment);
        }

        public override void UpdateInventory(ERPModuleItemsEntity entItems, string strUpdateStatus)
        {
            String transactionType = TransactionUtil.cstInventorySaleOrder;
            if (IsActionComplete)
                transactionType = TransactionUtil.cstInventoryShipment;

            SaleOrderItemsEntity entSaleOrderItem = (SaleOrderItemsEntity)entItems;
            if (strUpdateStatus == BusinessObject.DefaultAAStatus)
            {
                //Update Inventory Stock
                if (entSaleOrderItem.AAStatus == BusinessObject.DefaultAAStatus)
                {
                    int iICInventoryStockID = TransactionUtil.UpdateInventoryStock(
                                                entSaleOrderItem.FK_ICProductID, entSaleOrderItem.FK_ICProductAttributeID, entSaleOrderItem.FK_ICStockID, entSaleOrderItem.ARSaleOrderItemProductQty,
                                                transactionType);
                }
            }
            else if (strUpdateStatus == BusinessObject.DeletedAAStatus)
            {
                if (entSaleOrderItem.AAStatus == BusinessObject.DefaultAAStatus)
                {
                    //Update Inventory Stock
                    int iICInventoryStockID = TransactionUtil.UpdateInventoryStock(
                                                    entSaleOrderItem.FK_ICProductID, entSaleOrderItem.FK_ICProductAttributeID, entSaleOrderItem.FK_ICStockID, -entSaleOrderItem.ARSaleOrderItemProductQty,
                                                    transactionType);
                }
            }
        }

        public ARInvoicesInfo GenerateInvoiceFromSaleOrder(ARSaleOrdersInfo objSaleOrdersInfo)
        {
            ARInvoicesInfo objInvoicesInfo = new ARInvoicesInfo();
            THSUtil.CopyMainObjects(objSaleOrdersInfo, objInvoicesInfo);
            
            //Set own properties of invoice
            objInvoicesInfo.AACreatedUser = THSApp.CurrentUser;
            objInvoicesInfo.AACreatedDate = DateTime.Now;   
            objInvoicesInfo.ARInvoiceReference = objSaleOrdersInfo.ARSaleOrderNo;
            objInvoicesInfo.ARInvoiceStatus = Invoice.InvoiceModule.cstInvoiceStatusComplete;
            if (THSApp.CurrentCompanyInfo != null)
                objInvoicesInfo.FK_BRBranchID = THSApp.CurrentCompanyInfo.FK_BRBranchID;
            return objInvoicesInfo;
        }

        public void CreateInvoiceItemsFromSaleOrderItems(int iInvoiceID)
        {
            
            ARInvoiceItemsController objInvoiceItemsController = new ARInvoiceItemsController();

            foreach (SaleOrderItemsEntity item in ARSaleOrderItemsList)
            {
                ARInvoiceItemsInfo objInvoiceItemsInfo = new ARInvoiceItemsInfo();
                ARSaleOrderItemsInfo objSaleOrderItemsInfo = (ARSaleOrderItemsInfo)item.SetToBusinessObject(SaleOrder.SaleOrderEntities.strARSaleOrderItemsObjectName);
                THSUtil.CopyObjectItems(objSaleOrderItemsInfo, objInvoiceItemsInfo, Modules.Invoice.InvoiceEntities.strARInvoicesObjectName);
                objInvoiceItemsInfo.FK_ARInvoiceID = iInvoiceID;
                objInvoiceItemsController.CreateObject(objInvoiceItemsInfo);
            }
        }

        public void CancelLayBy()
        {
             using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    try
                    {
                        //Update sale order
                        ARSaleOrdersController objSaleOrdersController = new ARSaleOrdersController();
                        ARSaleOrdersInfo objSaleOrdersInfo = (ARSaleOrdersInfo)MainObject;
                        objSaleOrdersInfo.AAUpdatedDate = DateTime.Now;
                        objSaleOrdersInfo.AAUpdatedUser = THSApp.CurrentUser;
                        objSaleOrdersInfo.ARSaleOrderStatus = LayByModule.cstLayByStatusCancel;
                        objSaleOrdersController.UpdateObject(objSaleOrdersInfo);

                        //Update inventory
                        ARSaleOrderItemsList.UpdateInventory(BusinessObject.DeletedAAStatus);
                        
                        scope.Complete();

                        MessageBox.Show("Cancel successfully", "#Message#", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        scope.Dispose();
                    }
                }
        }
    }
}
